package com.asset.dispoal.file.appoint.service.command;


import com.alibaba.excel.EasyExcel;
import com.asset.dispoal.business.appoint.domain.db.mapper.AppointMapper;
import com.asset.dispoal.business.appoint.domain.dto.IdCaseState;
import com.asset.dispoal.business.bsAgreement.domain.db.entity.BsCaseAppointMapper;
import com.asset.dispoal.business.bsCase.domain.db.entity.CaseStateRecord;
import com.asset.dispoal.business.bsCase.domain.db.mapper.BsCaseMapper;
import com.asset.dispoal.business.bsCase.service.commom.CaseAbolishCaseCommand;
import com.asset.dispoal.business.bsCase.service.commom.CaseCloseCaseCommand;
import com.asset.dispoal.business.bsEvidenceRecognition.domain.db.entity.MatchSuccessEvidence;
import com.asset.dispoal.business.bsEvidenceRecognition.domain.db.entity.RemoveEvidenceContract;
import com.asset.dispoal.business.bsEvidenceRecognition.domain.db.mapper.BusinessDataManageMapper;
import com.asset.dispoal.business.bsEvidenceRecognition.dto.DeleteContractEvidenceRequest;
import com.asset.dispoal.commom.menus.AgreementCaseSateMenu;
import com.asset.dispoal.file.appoint.dto.AppointWithdrawalRequest;
import com.asset.dispoal.file.evidenceRecognition.domain.dto.IdCard;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tech.mhuang.pacebox.core.date.DateTimeUtil;
import tech.mhuang.pacebox.core.ddd.BaseCommand;
import tech.mhuang.pacebox.core.id.BaseIdeable;
import tech.mhuang.pacebox.core.util.CollectionUtil;
import tech.mhuang.pacebox.core.util.StringUtil;
import tech.mhuang.pacebox.springboot.core.local.GlobalHeaderThreadLocal;
import tech.mhuang.pacebox.springboot.protocol.Result;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
public class FileAppointWithdrawlCommand implements BaseCommand<AppointWithdrawalRequest, Result> {

    @Autowired
    AppointMapper appointMapper;

    @Autowired
    BsCaseMapper caseMapper;

    @Autowired
    BaseIdeable<String> snowFlake;

    @Autowired
    CaseAbolishCaseCommand caseAbolishCaseCommand;

    @Autowired
    CaseCloseCaseCommand caseCloseCaseCommand;

    @Autowired
    BusinessDataManageMapper businessDataManageMapper;

    @SneakyThrows
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public synchronized Result execute(AppointWithdrawalRequest request) {
        //TODO 此处逻辑后续换成策略模式进行处理
        String userId = GlobalHeaderThreadLocal.getOrException().getUserId();
        Date currentDate = DateTimeUtil.currentDate();
        //全部案件id
        List<IdCaseState> withDrawalCaseList = appointMapper.queryCaseIdListByAppointId(request.getAppointId());
        if (CollectionUtil.isEmpty(withDrawalCaseList)) {
            return Result.faild("当前批次没有可退的案件");
        }
        Set<String> appointSurplusSet = withDrawalCaseList.stream().map(IdCaseState::getId).collect(Collectors.toSet());
        //获取委派剩余数量
        int appointSurplusNum = appointSurplusSet.size();

        if ("2".equals(request.getMode())) {
            //批次退案
            request.setCaseIdList(appointSurplusSet);
        } else {
            if ("3".equals(request.getMode())) {
                //导入退案
                List<IdCard> idCardList = EasyExcel.read(request.getFile().getInputStream()).head(IdCard.class).sheet().doReadSync();
                if (CollectionUtil.isEmpty(idCardList)) {
                    return Result.faild("模板不存在身份证号");
                }
                Set<String> idCardSet = idCardList.stream().map(IdCard::getIdCard).collect(Collectors.toSet());
                request.setCaseIdList(appointMapper.queryCaseIdListByAppointIdAndIdCardList(request.getAppointId(), idCardSet));
            }
        }
        if (CollectionUtil.isEmpty(request.getCaseIdList())) {
            return Result.faild("退案的案件不存在");
        }
        //获取退案的案件id是那些
        Set<String> withdrawalCaseIdSet = appointSurplusSet.stream().filter(appointSurplus -> request.getCaseIdList().contains(appointSurplus)).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(withdrawalCaseIdSet)) {
            return Result.faild("退案的案件不存在");
        }

        if (CollectionUtil.isNotEmpty(request.getDelEvidenceTypeId())) {
            String assetInstBatchId = withDrawalCaseList.get(0).getAssetInstBatchId();
            Set<String> caseIdSet = new HashSet<>(request.getCaseIdList());
            //如果有删除的证据种类则进行组装查询案件的合同数据以及派案数据
            List<Map<String, String>> mapList = businessDataManageMapper.queryDataDetail(assetInstBatchId);
            List<Map<String, Object>> queryResult = businessDataManageMapper.queryResult(assetInstBatchId, mapList);
            queryResult = queryResult.stream().filter(query -> caseIdSet.contains(query.get("caseId"))).collect(Collectors.toList());
            //查询证据
            // 查询当前所有匹配上的原始证据
            List<MatchSuccessEvidence> matchSuccessEvidenceList = businessDataManageMapper.queryMatchSuccessEvidence(assetInstBatchId, null, null);
            //查询批次下全部删除的证据id和合同id
            List<RemoveEvidenceContract> removeEvidenceContractList = businessDataManageMapper.queryRemoveEvidenceContract(assetInstBatchId, null, null);
            //此处匹配上的证据进行删除
            for (Map<String, Object> agreementData : queryResult) {
                Set<String> removeEvidenceIdSet = removeEvidenceContractList.stream()
                        .filter(removeEvidenceType -> agreementData.get("contractId").equals(removeEvidenceType.getContractId()))
                        .map(RemoveEvidenceContract::getEvidenceId)
                        .collect(Collectors.toSet());
                List<MatchSuccessEvidence> matchSuccessEvidences = matchSuccessEvidenceList.parallelStream().filter(evidenceType -> !removeEvidenceIdSet.contains(evidenceType.getEvidenceId())).collect(Collectors.toList());
                for (MatchSuccessEvidence matchSuccessEvidence : matchSuccessEvidences) {
                    Boolean checkEvidenceType = Boolean.FALSE;
                    //无需匹配的证据直接返回当前成功
                    if (StringUtil.isEmpty(matchSuccessEvidence.getAlias())) {
                        checkEvidenceType = Boolean.TRUE;
                    }
                    //证据匹配上的返回成功
                    try {
                        if (agreementData.get(matchSuccessEvidence.getAlias()).equals(matchSuccessEvidence.getResult())) {
                            checkEvidenceType = Boolean.TRUE;
                        }
                    } catch (Exception ignore) {
                    }
                    if (checkEvidenceType) {
                        //删除证据关联关系
                        DeleteContractEvidenceRequest deleteContractEvidenceRequest = new DeleteContractEvidenceRequest();
                        deleteContractEvidenceRequest.setUserId(userId);
                        deleteContractEvidenceRequest.setEvidenceId(matchSuccessEvidence.getEvidenceId());
                        deleteContractEvidenceRequest.setAssetInstBatchId(assetInstBatchId);
                        deleteContractEvidenceRequest.setEvidenceTypeId(matchSuccessEvidence.getEvidenceTypeId());
                        deleteContractEvidenceRequest.setContractId((String) agreementData.get("contractId"));
                        businessDataManageMapper.deleteContractEvidence(deleteContractEvidenceRequest);
                    }
                }
            }
        }

        AgreementCaseSateMenu stateEnum;
        Boolean operatorMapper = Boolean.TRUE;
        String dropStatua;
        if ("0".equals(request.getType())) {
            //如果新案则不保留当前操作记录、并将对应案件返回到可派送阶段并可添加案件到当前状态，并写入历史
            //包含更新案件状态。可合并，以及删除委派并添加记录是退案到最新
            stateEnum = AgreementCaseSateMenu.WAIT_DELIVERY;
            operatorMapper = Boolean.FALSE;
            dropStatua = "-1";
        } else if (Integer.parseInt(request.getType()) < 3) {
            Integer checkInsert = appointMapper.queryDropById(request.getAppointId());
            if (checkInsert == 0) {
                appointMapper.insertDrop(request.getAppointId());
            }
            //添加到退案记录
            if ("1".equals(request.getType())) {
                //如果是正常退案则返回到正常退案情况，并写入历史、改变对应委派案件映射为正常退案，
                stateEnum = AgreementCaseSateMenu.WITHDRAWAL;
                dropStatua = "1";
            } else {
                //如果是瑕疵池退案则返回到瑕疵池状态，并写入历史，改变委派案件映射为瑕疵池退案
                stateEnum = AgreementCaseSateMenu.FLAW;
                dropStatua = "2";
            }
        } else if ("4".equals(request.getType())) {
            //废案
            for (String caseId : withdrawalCaseIdSet) {
                String reasonId = request.getWasteReasonId();
                caseAbolishCaseCommand.execute(caseId, reasonId);
            }
            return Result.ok();
        } else {
            //结案
            for (String caseId : withdrawalCaseIdSet) {
                caseCloseCaseCommand.execute(caseId);
            }
            return Result.ok();
        }
        //删除委派记录
        appointMapper.deleteMapperByAppointId(request.getAppointId(), withdrawalCaseIdSet);
        for (String caseId : withdrawalCaseIdSet) {
            String oldCaseState = withDrawalCaseList.stream().filter(cases -> caseId.equals(cases.getId())).map(IdCaseState::getState).findFirst().get();
            //更新案件状态
            caseMapper.updateState(caseId, userId, stateEnum.getLabel(), stateEnum.getMerge());
            //变更案件记录
            CaseStateRecord caseStateRecord = new CaseStateRecord();
            caseStateRecord.setId(snowFlake.generateId());
            caseStateRecord.setCaseId(caseId);
            caseStateRecord.setCreateUser(userId);
            caseStateRecord.setCreateTime(currentDate);
            caseStateRecord.setOldState(oldCaseState);
            caseStateRecord.setNewState(stateEnum.getLabel());
            caseMapper.insertStateRecord(caseStateRecord);
            BsCaseAppointMapper caseAppointMapper = new BsCaseAppointMapper();
            caseAppointMapper.setAppointId(request.getAppointId());
            caseAppointMapper.setId(snowFlake.generateId());
            caseAppointMapper.setDropStatus(dropStatua);
            caseAppointMapper.setOperateTime(currentDate);
            caseAppointMapper.setCaseId(caseId);
            caseAppointMapper.setFlawId(request.getFlawId());
            caseAppointMapper.setOperateUser(GlobalHeaderThreadLocal.getOrException().getUserId());
            caseAppointMapper.setWithdrawalUserId(userId);
            caseAppointMapper.setWithdrawalTime(currentDate);
            appointMapper.insertMapperRecord(caseAppointMapper);
            //如果需要插入，则插入记录
            if (operatorMapper) {
                appointMapper.insertMapper(caseAppointMapper);
            }
        }
        if (withdrawalCaseIdSet.size() == appointSurplusNum) {
            //如果退完了则删除当前委派记录，没有退案则保留
            appointMapper.deleteById(request.getAppointId());
        }
        return Result.ok();
    }
}
